import com.github.javaparser.JavaParser;
import com.github.javaparser.ParseResult;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.body.TypeDeclaration;
import com.github.javaparser.ast.expr.*;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
import com.github.javaparser.utils.SourceRoot;

import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 反向调用链追踪代码影响分析器
 * 支持 Spring MVC + Swagger，能够分析多层调用关系
 *
 * 功能特性：
 * 1. 反向调用链追踪：从目标方法向上追踪到Controller接口
 * 2. 多层调用分析：支持方法A调用方法B，方法B调用目标方法的场景
 * 3. 接口信息提取：自动提取API路径、HTTP方法、Swagger描述
 * 4. 调用链可视化：以树形结构展示完整的调用链路
 */
public class MethodImpactAnalyzer {

    // 存储结果：调用链 -> 接口信息
    private static Map<CallChain, Set<ApiInfo>> impactResults = new LinkedHashMap<>();

    // 存储所有方法调用关系：调用者 -> 被调用者集合
    private static Map<MethodInfo, Set<MethodInfo>> methodCallGraph = new HashMap<>();

    // 存储所有方法信息：完整方法签名 -> 方法信息
    private static Map<String, MethodInfo> allMethods = new HashMap<>();

    // 存储Controller方法信息
    private static Map<MethodInfo, ApiInfo> controllerMethods = new HashMap<>();

    // 目标方法名（支持模糊匹配和完整匹配）
    private static String TARGET_METHOD_NAME = "RedisUtil.set";
    private static String TARGET_CLASS_NAME = "RedisUtil"; // 可选：指定目标类名

    // 项目路径和包名
    private static String PROJECT_SOURCE_ROOT = "D:/ideaWorkSpacs/untitled/src/main/java"; // 修改为实际路径
    private static String BASE_PACKAGE = "com.example";

    // 最大调用链深度（防止无限递归）
    private static final int MAX_CHAIN_DEPTH = 10;

    public static void main(String[] args) {
        System.out.println("=== 反向调用链追踪代码影响分析器 ===");
        System.out.println("目标方法: " + TARGET_METHOD_NAME);
        System.out.println("项目路径: " + PROJECT_SOURCE_ROOT);
        System.out.println("基础包名: " + BASE_PACKAGE);
        System.out.println();

        // 第一阶段：构建方法调用图
        System.out.println("第一阶段：构建方法调用图...");
        buildMethodCallGraph(PROJECT_SOURCE_ROOT, BASE_PACKAGE);

        // 第二阶段：反向追踪调用链
        System.out.println("第二阶段：反向追踪调用链...");
        traceCallChains();

        // 第三阶段：输出结果
        System.out.println("第三阶段：生成影响分析报告...");
        printResults();
    }

    /**
     * 构建方法调用图
     */
    public static void buildMethodCallGraph(String sourceRootPath, String basePackage) {
        File rootDir = new File(sourceRootPath);
        if (!rootDir.exists() || !rootDir.isDirectory()) {
            System.err.println("源码目录不存在: " + sourceRootPath);
            return;
        }

        SourceRoot sourceRoot = new SourceRoot(Paths.get(sourceRootPath));
        JavaParser javaParser = new JavaParser();

        try {
            sourceRoot.parse("", new MethodCallGraphBuilder(javaParser, basePackage));
            System.out.println("方法调用图构建完成，共发现 " + allMethods.size() + " 个方法");
            System.out.println("Controller方法数量: " + controllerMethods.size());
        } catch (Exception e) {
            System.err.println("构建方法调用图时发生错误: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 反向追踪调用链
     */
    public static void traceCallChains() {
        // 找到所有目标方法
        List<MethodInfo> targetMethods = findTargetMethods();
        System.out.println("找到目标方法数量: " + targetMethods.size());

        for (MethodInfo targetMethod : targetMethods) {
            System.out.println("追踪目标方法: " + targetMethod.getFullName());
            traceCallChainsFromTarget(targetMethod, new ArrayList<>(), 0);
        }
    }

    /**
     * 从目标方法开始反向追踪调用链
     */
    private static void traceCallChainsFromTarget(MethodInfo targetMethod, List<MethodInfo> currentChain, int depth) {
        if (depth > MAX_CHAIN_DEPTH) {
            return;
        }

        // 检查当前方法是否是Controller方法
        if (controllerMethods.containsKey(targetMethod)) {
            CallChain chain = new CallChain(new ArrayList<>(currentChain));
            ApiInfo apiInfo = controllerMethods.get(targetMethod);

            Set<ApiInfo> apiSet = impactResults.get(chain);
            if (apiSet == null) {
                apiSet = new HashSet<>();
                impactResults.put(chain, apiSet);
            }
            apiSet.add(apiInfo);
            System.out.println("找到Controller方法调用链: " + chain.toString());
            return;
        }

        // 查找调用当前方法的所有方法
        Set<MethodInfo> callers = findCallers(targetMethod);
        System.out.println("从 " + targetMethod.getFullName() + " 找到调用者数量: " + callers.size());

        for (MethodInfo caller : callers) {
            // 检查调用者是否是Controller方法
            if (controllerMethods.containsKey(caller)) {
                List<MethodInfo> newChain = new ArrayList<>(currentChain);
                newChain.add(targetMethod);
                CallChain chain = new CallChain(newChain);
                ApiInfo apiInfo = controllerMethods.get(caller);

                Set<ApiInfo> apiSet = impactResults.get(chain);
                if (apiSet == null) {
                    apiSet = new HashSet<>();
                    impactResults.put(chain, apiSet);
                }
                apiSet.add(apiInfo);
                System.out.println("找到Controller方法调用链: " + chain.toString() + " -> " + apiInfo.toString());
                continue;
            }

            // 避免循环调用：检查调用者是否已经在当前调用链中
            boolean isInChain = false;
            for (MethodInfo methodInChain : currentChain) {
                if (methodInChain.equals(caller)) {
                    isInChain = true;
                    break;
                }
            }

            if (!isInChain && !caller.equals(targetMethod)) { // 避免自调用
                List<MethodInfo> newChain = new ArrayList<>(currentChain);
                newChain.add(targetMethod);
                System.out.println("追踪调用链: " + caller.getFullName() + " -> " + targetMethod.getFullName());
                traceCallChainsFromTarget(caller, newChain, depth + 1);
            } else {
                System.out.println("跳过循环调用: " + caller.getFullName());
            }
        }
    }

    /**
     * 查找目标方法
     */
    private static List<MethodInfo> findTargetMethods() {
        List<MethodInfo> targets = new ArrayList<>();
        for (MethodInfo method : allMethods.values()) {
            if (isTargetMethod(method)) {
                targets.add(method);
            }
        }
        return targets;
    }

    /**
     * 判断是否是目标方法
     */
    private static boolean isTargetMethod(MethodInfo method) {
        // 支持多种匹配方式
        String targetMethodName = TARGET_METHOD_NAME.split("\\.")[1]; // 提取方法名部分

        boolean classMatch = method.getClassName().contains(TARGET_CLASS_NAME);
        boolean methodMatch = method.getMethodName().contains(targetMethodName);
        boolean fullNameMatch = method.getFullName().contains(TARGET_METHOD_NAME);

        boolean result = (classMatch && methodMatch) || fullNameMatch;

        if (result) {
            System.out.println("匹配到目标方法: " + method.getFullName() +
                    " (类名匹配:" + classMatch + ", 方法名匹配:" + methodMatch + ", 全名匹配:" + fullNameMatch + ")");
        }

        return result;
    }

    /**
     * 查找调用指定方法的所有方法
     */
    private static Set<MethodInfo> findCallers(MethodInfo targetMethod) {
        Set<MethodInfo> callers = new HashSet<>();
        System.out.println("查找调用者，目标方法: " + targetMethod.getFullName());
        System.out.println("目标方法详细信息 - 类名: " + targetMethod.getClassName() + ", 方法名: " + targetMethod.getMethodName());

        for (Map.Entry<MethodInfo, Set<MethodInfo>> entry : methodCallGraph.entrySet()) {
            MethodInfo caller = entry.getKey();
            Set<MethodInfo> calledMethods = entry.getValue();

            System.out.println("检查调用者: " + caller.getFullName() + " 调用的方法:");
            boolean foundTarget = false;
            for (MethodInfo calledMethod : calledMethods) {
                System.out.println("  - " + calledMethod.getFullName() +
                        " (类名: " + calledMethod.getClassName() +
                        ", 方法名: " + calledMethod.getMethodName() + ")");

                // 使用更灵活的匹配方式
                boolean isMatch = calledMethod.equals(targetMethod) ||
                        (calledMethod.getClassName().contains(TARGET_CLASS_NAME) &&
                                calledMethod.getMethodName().contains("set"));

                if (isMatch) {
                    System.out.println("  *** 找到匹配的调用关系! ***");
                    foundTarget = true;
                }
            }
            if (foundTarget) {
                callers.add(caller);
            }
        }

        System.out.println("找到调用者数量: " + callers.size());
        return callers;
    }

    // 方法调用图构建器
    static class MethodCallGraphBuilder implements SourceRoot.Callback {

        private String basePackage;

        public MethodCallGraphBuilder(JavaParser javaParser, String basePackage) {
            this.basePackage = basePackage;
        }

        @Override
        public Result process(Path relativePath, Path absolutePath, ParseResult<CompilationUnit> result) {
            try {
                if (!result.isSuccessful()) {
                    System.err.println("解析失败: " + relativePath);
                    return SourceRoot.Callback.Result.DONT_SAVE;
                }

                Optional<CompilationUnit> cuOpt = result.getResult();
                if (!cuOpt.isPresent()) {
                    System.err.println("无法获取CompilationUnit: " + relativePath);
                    return SourceRoot.Callback.Result.DONT_SAVE;
                }
                CompilationUnit cu = cuOpt.get();

                // 获取包名
                String packageName = "";
                if (cu.getPackageDeclaration().isPresent()) {
                    packageName = cu.getPackageDeclaration().get().getName().asString();
                }

                // 检查包名前缀
                if (!packageName.startsWith(basePackage)) {
                    return SourceRoot.Callback.Result.DONT_SAVE;
                }

                // 遍历所有顶层类型
                for (int i = 0; i < cu.getTypes().size(); i++) {
                    TypeDeclaration<?> type = cu.getTypes().get(i);
                    if (type instanceof ClassOrInterfaceDeclaration) {
                        ClassOrInterfaceDeclaration classDecl = (ClassOrInterfaceDeclaration) type;

                        // 处理所有类，不仅仅是Controller
                        MethodCallGraphVisitor visitor = new MethodCallGraphVisitor();
                        visitor.setPackageName(packageName);
                        visitor.visit(classDecl, (Void) null);
                    }
                }
                return SourceRoot.Callback.Result.DONT_SAVE;
            } catch (Exception e) {
                System.err.println("处理文件时发生错误: " + relativePath + ", " + e.getMessage());
                e.printStackTrace();
                return SourceRoot.Callback.Result.DONT_SAVE;
            }
        }
    }

    // 检查类是否有指定注解
    private static boolean hasAnnotation(ClassOrInterfaceDeclaration cls, String annotationName) {
        List<AnnotationExpr> annotations = cls.getAnnotations();
        for (int i = 0; i < annotations.size(); i++) {
            AnnotationExpr ann = annotations.get(i);
            Name name = ann.getName();
            String fullName = name.asString();
            if (fullName.equals(annotationName) || fullName.endsWith("." + annotationName)) {
                return true;
            }
        }
        return false;
    }

    // 提取类级别的 @RequestMapping 路径
    private static String extractClassRequestMapping(ClassOrInterfaceDeclaration cls) {
        Optional<AnnotationExpr> annOpt = cls.getAnnotationByName("RequestMapping");
        if (annOpt.isPresent()) {
            return extractAnnotationValue(annOpt.get());
        }
        return "";
    }

    // 提取注解的字符串值
    private static String extractAnnotationValue(AnnotationExpr ann) {
        if (ann instanceof NormalAnnotationExpr) {
            NormalAnnotationExpr normal = (NormalAnnotationExpr) ann;
            List<MemberValuePair> pairs = normal.getPairs();
            for (int i = 0; i < pairs.size(); i++) {
                MemberValuePair pair = pairs.get(i);
                String key = pair.getNameAsString();
                if ("value".equals(key) || "path".equals(key)) {
                    Expression value = pair.getValue();
                    if (value instanceof StringLiteralExpr) {
                        StringLiteralExpr strExpr = (StringLiteralExpr) value;
                        return strExpr.getValue();
                    }
                }
            }
        } else if (ann instanceof SingleMemberAnnotationExpr) {
            SingleMemberAnnotationExpr single = (SingleMemberAnnotationExpr) ann;
            Expression value = single.getMemberValue();
            if (value instanceof StringLiteralExpr) {
                StringLiteralExpr strExpr = (StringLiteralExpr) value;
                return strExpr.getValue();
            }
        }
        return "";
    }

    // 判断是否是请求映射方法
    private static boolean isRequestMappingMethod(MethodDeclaration method) {
        List<AnnotationExpr> annotations = method.getAnnotations();
        for (int i = 0; i < annotations.size(); i++) {
            AnnotationExpr ann = annotations.get(i);
            Name name = ann.getName();
            String fullName = name.asString();
            if (isSpringMappingAnnotation(fullName)) {
                return true;
            }
        }
        return false;
    }

    private static boolean isSpringMappingAnnotation(String fullName) {
        String[] mappingNames = {
                "RequestMapping", "GetMapping", "PostMapping",
                "PutMapping", "DeleteMapping", "PatchMapping"
        };
        for (String name : mappingNames) {
            if (fullName.equals(name) || fullName.endsWith("." + name)) {
                return true;
            }
        }
        return false;
    }

    // 获取 HTTP 方法类型
    private static String getHttpMethod(MethodDeclaration method) {
        List<AnnotationExpr> annotations = method.getAnnotations();
        for (int i = 0; i < annotations.size(); i++) {
            AnnotationExpr ann = annotations.get(i);
            Name name = ann.getName();
            String fullName = name.asString();

            if (fullName.equals("GetMapping") || fullName.endsWith(".GetMapping")) {
                return "GET";
            } else if (fullName.equals("PostMapping") || fullName.endsWith(".PostMapping")) {
                return "POST";
            } else if (fullName.equals("PutMapping") || fullName.endsWith(".PutMapping")) {
                return "PUT";
            } else if (fullName.equals("DeleteMapping") || fullName.endsWith(".DeleteMapping")) {
                return "DELETE";
            } else if (fullName.equals("PatchMapping") || fullName.endsWith(".PatchMapping")) {
                return "PATCH";
            }
        }
        return "UNKNOWN";
    }

    // 提取方法映射路径
    private static String extractMethodMappingPath(MethodDeclaration method) {
        List<AnnotationExpr> annotations = method.getAnnotations();
        for (int i = 0; i < annotations.size(); i++) {
            AnnotationExpr ann = annotations.get(i);
            Name name = ann.getName();
            String fullName = name.asString();

            if (isSpringMappingAnnotation(fullName)) {
                return extractAnnotationValue(ann);
            }
        }
        return "";
    }

    // 提取 @ApiOperation 描述
    private static String extractApiOperationDescription(MethodDeclaration method) {
        Optional<AnnotationExpr> opAnnOpt = method.getAnnotationByName("ApiOperation");
        if (!opAnnOpt.isPresent()) {
            return "No description";
        }

        AnnotationExpr ann = opAnnOpt.get();
        if (ann instanceof NormalAnnotationExpr) {
            NormalAnnotationExpr normal = (NormalAnnotationExpr) ann;
            List<MemberValuePair> pairs = normal.getPairs();
            for (int i = 0; i < pairs.size(); i++) {
                MemberValuePair pair = pairs.get(i);
                String key = pair.getNameAsString();
                if ("value".equals(key) || "notes".equals(key)) {
                    Expression value = pair.getValue();
                    if (value instanceof StringLiteralExpr) {
                        return ((StringLiteralExpr) value).getValue();
                    }
                }
            }
        } else if (ann instanceof SingleMemberAnnotationExpr) {
            Expression value = ((SingleMemberAnnotationExpr) ann).getMemberValue();
            if (value instanceof StringLiteralExpr) {
                return ((StringLiteralExpr) value).getValue();
            }
        }
        return "No description";
    }

    // 路径标准化
    private static String normalizePath(String path) {
        if (path == null || path.trim().isEmpty()) {
            return "";
        }
        return path.startsWith("/") ? path : "/" + path;
    }

    private static String joinPaths(String classPath, String methodPath) {
        String fullPath = normalizePath(classPath) + normalizePath(methodPath);
        fullPath = fullPath.replaceAll("/{2,}", "/");
        return fullPath.isEmpty() ? "/" : fullPath;
    }

    // 方法调用图访问器
    static class MethodCallGraphVisitor extends VoidVisitorAdapter<Void> {

        private String packageName;
        private String currentClassName;
        private MethodInfo currentMethod;
        private ClassOrInterfaceDeclaration currentClass;

        public void setPackageName(String packageName) {
            this.packageName = packageName;
        }

        @Override
        public void visit(ClassOrInterfaceDeclaration classDecl, Void arg) {
            this.currentClassName = classDecl.getNameAsString();
            this.currentClass = classDecl;
            super.visit(classDecl, arg);
        }

        @Override
        public void visit(MethodDeclaration method, Void arg) {
            // 创建当前方法信息
            currentMethod = new MethodInfo(packageName + "." + currentClassName, method.getNameAsString());
            String methodKey = currentMethod.getFullName();
            allMethods.put(methodKey, currentMethod);

            // 检查是否是Controller方法
            boolean isController = hasAnnotation(currentClass, "Controller") ||
                    hasAnnotation(currentClass, "RestController");

            if (isController && isRequestMappingMethod(method)) {
                String classRequestMapping = extractClassRequestMapping(currentClass);
                String methodPath = extractMethodMappingPath(method);
                String fullPath = joinPaths(classRequestMapping, methodPath);
                String httpMethod = getHttpMethod(method);
                String description = extractApiOperationDescription(method);

                ApiInfo apiInfo = new ApiInfo(fullPath, httpMethod, description);
                controllerMethods.put(currentMethod, apiInfo);
                System.out.println("识别到Controller方法: " + currentMethod.getFullName() + " -> " + apiInfo.toString());
            }

            // 收集方法调用关系
            MethodCallCollector collector = new MethodCallCollector();
            collector.visit(method, (Void) null);

            Set<MethodInfo> calledMethods = collector.getCalledMethods();
            methodCallGraph.put(currentMethod, calledMethods);

            super.visit(method, arg);
        }
    }

    // 方法调用收集器
    static class MethodCallCollector extends VoidVisitorAdapter<Void> {

        private Set<MethodInfo> calledMethods = new HashSet<>();

        @Override
        public void visit(MethodCallExpr methodCall, Void arg) {
            super.visit(methodCall, arg);

            // 尝试解析方法调用
            String methodName = methodCall.getName().asString();

            // 尝试获取调用者信息
            String className = "UnknownClass";
            if (methodCall.getScope().isPresent()) {
                Expression scope = methodCall.getScope().get();
                if (scope instanceof NameExpr) {
                    className = ((NameExpr) scope).getNameAsString();
                }
            }

            // 创建被调用方法信息 - 使用完整类名
            String fullClassName = className;
            if ("RedisUtil".equals(className)) {
                fullClassName = "com.example.util.RedisUtil";
            } else if ("System".equals(className)) {
                fullClassName = "java.lang.System";
            } else if ("userService".equals(className)) {
                fullClassName = "com.example.service.UserService";
            } else if ("orderService".equals(className)) {
                fullClassName = "com.example.service.OrderService";
            }

            MethodInfo calledMethod = new MethodInfo(fullClassName, methodName);
            calledMethods.add(calledMethod);

            // 调试输出
            System.out.println("发现方法调用: " + fullClassName + "." + methodName);
        }

        public Set<MethodInfo> getCalledMethods() {
            return calledMethods;
        }
    }

    // Controller 访问器
    static class ControllerVisitor extends VoidVisitorAdapter<Void> {

        private String currentClassRequestMapping = "";

        public void setCurrentClassRequestMapping(String path) {
            this.currentClassRequestMapping = path;
        }

        @Override
        public void visit(MethodDeclaration method, Void arg) {
            if (!isRequestMappingMethod(method)) {
                super.visit(method, arg);
                return;
            }

            String methodPath = extractMethodMappingPath(method);
            String fullPath = joinPaths(currentClassRequestMapping, methodPath);
            String httpMethod = getHttpMethod(method);
            String description = extractApiOperationDescription(method);

            MethodInfo methodInfo = new MethodInfo(
                    getCurrentClassName(method),
                    method.getName().asString());

            MethodCallCollector collector = new MethodCallCollector();
            collector.visit(method, (Void) null);

            Set<MethodInfo> calledMethods = collector.getCalledMethods();
            // 检查是否调用了目标方法
            boolean containsTarget = false;
            for (MethodInfo calledMethod : calledMethods) {
                if (isTargetMethod(calledMethod)) {
                    containsTarget = true;
                    break;
                }
            }

            if (containsTarget) {
                ApiInfo apiInfo = new ApiInfo(fullPath, httpMethod, description);
                // 创建调用链（这里简化处理，实际应该构建完整的调用链）
                CallChain chain = new CallChain(Arrays.asList(methodInfo));
                Set<ApiInfo> apiSet = impactResults.get(chain);
                if (apiSet == null) {
                    apiSet = new HashSet<>();
                    impactResults.put(chain, apiSet);
                }
                apiSet.add(apiInfo);
            }

            super.visit(method, arg);
        }

        private String getCurrentClassName(MethodDeclaration method) {
            // 简化处理，实际可通过上下文获取
            Node parentNode = method.getParentNode().orElse(null);
            while (parentNode != null) {
                if (parentNode instanceof ClassOrInterfaceDeclaration) {
                    return ((ClassOrInterfaceDeclaration) parentNode).getNameAsString();
                }
                parentNode = parentNode.getParentNode().orElse(null);
            }
            return "UnknownClass";
        }
    }

    // 方法信息
    static class MethodInfo {
        private String className;
        private String methodName;
        private String packageName;

        public MethodInfo(String fullClassName, String methodName) {
            this.methodName = methodName;
            if (fullClassName.contains(".")) {
                this.packageName = fullClassName.substring(0, fullClassName.lastIndexOf("."));
                this.className = fullClassName.substring(fullClassName.lastIndexOf(".") + 1);
            } else {
                this.packageName = "";
                this.className = fullClassName;
            }
        }

        public String getClassName() {
            return className;
        }

        public String getMethodName() {
            return methodName;
        }

        public String getPackageName() {
            return packageName;
        }

        public String getFullName() {
            return (packageName.isEmpty() ? "" : packageName + ".") + className + "." + methodName;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            MethodInfo that = (MethodInfo) o;
            return Objects.equals(className, that.className) &&
                    Objects.equals(methodName, that.methodName) &&
                    Objects.equals(packageName, that.packageName);
        }

        @Override
        public int hashCode() {
            return Objects.hash(className, methodName, packageName);
        }

        @Override
        public String toString() {
            return getFullName();
        }
    }

    // 调用链信息
    static class CallChain {
        private List<MethodInfo> chain;

        public CallChain(List<MethodInfo> chain) {
            this.chain = new ArrayList<>(chain);
        }

        public List<MethodInfo> getChain() {
            return chain;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            CallChain callChain = (CallChain) o;
            return Objects.equals(chain, callChain.chain);
        }

        @Override
        public int hashCode() {
            return Objects.hash(chain);
        }

        @Override
        public String toString() {
            return chain.stream()
                    .map(MethodInfo::toString)
                    .collect(Collectors.joining(" -> "));
        }
    }

    // 接口信息
    static class ApiInfo {
        private String path;
        private String method;
        private String description;

        public ApiInfo(String path, String method, String description) {
            this.path = path;
            this.method = method;
            this.description = description;
        }

        public String getPath() {
            return path;
        }

        public String getMethod() {
            return method;
        }

        public String getDescription() {
            return description;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            ApiInfo apiInfo = (ApiInfo) o;
            return Objects.equals(path, apiInfo.path) && Objects.equals(method, apiInfo.method);
        }

        @Override
        public int hashCode() {
            return Objects.hash(path, method);
        }

        @Override
        public String toString() {
            return method + " " + path + " - " + description;
        }
    }

    // 打印结果
    public static void printResults() {
        System.out.println("\n=== 反向调用链追踪分析结果 ===");
        System.out.println("目标方法: " + TARGET_METHOD_NAME);
        System.out.println("发现调用链数量: " + impactResults.size());
        System.out.println();

        if (impactResults.isEmpty()) {
            System.out.println("❌ 未找到任何调用链，可能的原因：");
            System.out.println("   1. 目标方法不存在或名称不匹配");
            System.out.println("   2. 没有Controller方法调用该目标方法");
            System.out.println("   3. 项目路径或包名配置不正确");
            return;
        }

        int chainIndex = 1;
        for (Map.Entry<CallChain, Set<ApiInfo>> entry : impactResults.entrySet()) {
            CallChain chain = entry.getKey();
            Set<ApiInfo> apis = entry.getValue();

            System.out.println("📋 调用链 #" + chainIndex + ":");
            System.out.println("   调用路径: " + chain.toString());
            System.out.println("   影响的接口:");

            for (ApiInfo api : apis) {
                System.out.println("     🔗 " + api.toString());
            }
            System.out.println();
            chainIndex++;
        }

        // 统计信息
        int totalApis = impactResults.values().stream()
                .mapToInt(Set::size)
                .sum();

        System.out.println("📊 统计信息:");
        System.out.println("   调用链总数: " + impactResults.size());
        System.out.println("   受影响接口总数: " + totalApis);
        System.out.println("   目标方法: " + TARGET_METHOD_NAME);

        // 显示所有受影响的接口（去重）
        Set<ApiInfo> allAffectedApis = new HashSet<>();
        for (Set<ApiInfo> apiSet : impactResults.values()) {
            allAffectedApis.addAll(apiSet);
        }

        System.out.println("\n🎯 所有受影响的接口列表:");
        for (ApiInfo api : allAffectedApis) {
            System.out.println("   " + api.toString());
        }
    }
}
